`timescale 1ns/1ns

module multiplier(
 iClk, 	 	 // input clock
 iReset, 	 	 // reset signal
 iReady, 	 	 // indicates inputs are ready
 oDone, 	 	 // indicates that the result is ready
 iMultiplier, 	 	 // 8-bit multiplier [7:0]
 iMultiplicand, 	 // 8-bit multiplicand [7:0]
 oProduct);
input iClk, iReset, iReady;
input [7:0] iMultiplier, iMultiplicand;
output oDone;
output [15:0] oProduct;
wire[7:0] Mxout, wSum;
wire zero, wCarry, wShift;
assign oProduct[7:0] = iMultiplier[7:0];
assign zero = 8'b00000000;
MUX2x1 Mux1(zero, oProduct[15:8], oProduct[0], Mxout[7:0]);
Adder_8bit A1(iMultiplicand[7:0] , Mxout[7:0] , wSum[7:0], wCarry);
assign oProduct[15:8] = wSum[7:0];
R_Shifter RS1(oProduct, wShift);
endmodule

module MUX2x1(i0, i1, sel, out);
input [7:0] i0, i1;
input sel;
output [7:0] out;
wire w1,w2,w3;
and(w1, i0, ~sel);
and(w1, i1, sel);
or(w3, w1, w2);
assign out=w3;
endmodule

module R_Shifter(in, out);
input [15:0] in;
output [15:0] out;
assign out[15] = 0;
assign out[14] = in[15];
assign out[13] = in[14];
assign out[12] = in[13];
assign out[11] = in[12];
assign out[10] = in[11];
assign out[9] = in[10];
assign out[8] = in[9];
assign out[7] = in[8];
assign out[6] = in[7];
assign out[5] = in[6];
assign out[4] = in[5];
assign out[3] = in[4];
assign out[2] = in[3];
assign out[1] = in[2];
endmodule



module Adder_8bit(i0, i1, sum, c);
input [7:0] i0, i1;
output [7:0] sum;
output c;
wire [7:0] cout, sum;
Full_adder FA1(i0[0], i1[0], 0, cout[0], sum[0]);
Full_adder FA2(i0[1], i1[1], cout[0], cout[1], sum[1]);
Full_adder FA3(i0[2], i1[2], cout[1], cout[2], sum[2]);
Full_adder FA4(i0[3], i1[3], cout[2], cout[3], sum[3]);
Full_adder FA5(i0[4], i1[4], cout[3], cout[4], sum[4]);
Full_adder FA6(i0[5], i1[5], cout[4], cout[5], sum[5]);
Full_adder FA7(i0[6], i1[6], cout[5], cout[6], sum[6]);
Full_adder FA8(i0[7], i1[7], cout[6], cout[7], sum[7]);
assign c = cout[7];
endmodule

module Full_adder(a, b, Cin, Cout, sum);
input a, b, Cin;
output Cout, sum;
wire w1, w2, w3, w4, w5;
and A1(w1, a, b);

xor X1(w2, a, b);
xor X2(w3, w2, Cin); // sum = a x b x c

and A2(w4, Cin, w2);
or O1(w5, w1, w4); // carry out = a*b + cin*(axb)

assign sum = w3;
assign Cout = w5;
endmodulemodule multiplier(
  iClk, // input clock
  iReset, // reset signal
  iReady, // indicates inputs are ready
  oDone, // indicates that the result is ready
  iMultiplier, // 8-bit multiplier [7:0]
  iMultiplicand, // 8-bit multiplicand [7:0]
  oProduct // 16-bit product [15:0]
);

  input iClk, iReset, iReady;
  input [7:0] iMultiplier, iMultiplicand;
  output [15:0] oProduct;
  output oDone;
  
  wire [15:0]tProduct;
  wire [7:0]outputmux;
  wire [7:0]outputFA;
  wire outputFA_Cout;
  wire [15:0]outputLink;
  wire [15:0]outputShifter;
  wire [7:0]wMultiplier;
  wire [7:0]wMultiplicand;
  wire sign;
  
  assign oDone=1'b0;
  xor x1(sign, iMultiplier, iMultiplicand);
  Register_8bit Reg1(iMultiplier, iReset, iReady, iClk, wMultiplier);
  Register_8bit Reg2(iMultiplicand, iReset, iReady, iClk, wMultiplicand);
  Link L0(tProduct, wMultiplier, wMultiplicand);
  
  assign wMultiplicand[7]=0;
  assign outputmux[7]=0; // delete sign for calculate
  
  //First Loop
  Mux_2x1_8bit M1(8'b00000000, tProduct[15:8], tProduct[0], outputmux);
  Full_Adder_8bit FA1(wMultiplicand, outputmux, outputFA, outputFA_Cout);
  Link L1(outputFA, tProduct[7:0], outputLink);
  Shifter S1(outputLink, tProduct);
  //Second Loop
  Mux_2x1_8bit M2(8'b00000000, tProduct[15:8], tProduct[0], outputmux);
  Full_Adder_8bit FA2(wMultiplicand, outputmux, outputFA, outputFA_Cout);
  Link L2(outputFA, tProduct[7:0], outputLink);
  Shifter S2(outputLink, tProduct);
  //Thrid Loop
  Mux_2x1_8bit M3(8'b00000000, tProduct[15:8], tProduct[0], outputmux);
  Full_Adder_8bit FA3(wMultiplicand, outputmux, outputFA, outputFA_Cout);
  Link L3(outputFA, tProduct[7:0], outputLink);
  Shifter S3(outputLink, tProduct);
  //Fourth Loop
  Mux_2x1_8bit M4(8'b00000000, tProduct[15:8], tProduct[0], outputmux);
  Full_Adder_8bit FA4(wMultiplicand, outputmux, outputFA, outputFA_Cout);
  Link L4(outputFA, tProduct[7:0], outputLink);
  Shifter S4(outputLink, tProduct);
  //Fifth Loop
  Mux_2x1_8bit M5(8'b00000000, tProduct[15:8], tProduct[0], outputmux);
  Full_Adder_8bit FA5(wMultiplicand, outputmux, outputFA, outputFA_Cout);
  Link L5(outputFA, tProduct[7:0], outputLink);
  Shifter S5(outputLink, tProduct);
  //Sixth Loop
  Mux_2x1_8bit M6(8'b00000000, tProduct[15:8], tProduct[0], outputmux);
  Full_Adder_8bit FA6(wMultiplicand, outputmux, outputFA, outputFA_Cout);
  Link L6(outputFA, tProduct[7:0], outputLink);
  Shifter S6(outputLink, tProduct);
  //Seventh Loop
  Mux_2x1_8bit M7(8'b00000000, tProduct[15:8], tProduct[0], outputmux);
  Full_Adder_8bit FA7(wMultiplicand, outputmux, outputFA, outputFA_Cout);
  Link L7(outputFA, tProduct[7:0], outputLink);
  Shifter S7(outputLink, tProduct);
  
  assign tProduct[15]=sign;
  assign oProduct=tProduct;
  assign oDone=1'b1;

endmodule

module Half_Adder(s, c, a, b);
  input a, b;
  output s, c;
  
  xor x1(s, a, b);
  and a1(c, a, b);
endmodule

module Full_Adder(A, B, C_in, S, C_out);
  input A, B, C_in;
  output S, C_out;
  wire w1, w2;
  
  Half_Adder H1(w1, w2, A, B);
  Half_Adder H2(S, w3, w1, C_in);
  or o1(C_out, w3, w2);  
endmodule

module Full_Adder_8bit(A, B, S, C_out);
  
  input [7:0] A, B;
  output [7:0] S;
  output C_out;
  wire [7:0] w;
  
  Full_Adder F0(S[0], w[0], 1'b0, A[0], B[0]);
  Full_Adder F1(S[1], w[1], w[0], A[1], B[1]);
  Full_Adder F2(S[2], w[2], w[1], A[2], B[2]);
  Full_Adder F3(S[3], w[3], w[2], A[3], B[3]);
  Full_Adder F4(S[4], w[4], w[3], A[4], B[4]);
  Full_Adder F5(S[5], w[5], w[4], A[5], B[5]);
  Full_Adder F6(S[6], w[6], w[5], A[6], B[6]);
  Full_Adder F7(S[7], w[7], w[6], A[7], B[7]);
  
  assign C_out=w[7];
  
endmodule
  
module Mux_2x1_8bit(i0, i1, sel, out);
  
  input [7:0] i0, i1;
  input sel;
  output [7:0] out;
  wire [7:0] w1, w2;
  
  and a10(w1[0], sel, i0[0]);
  and a11(w1[1], sel, i0[1]);
  and a12(w1[2], sel, i0[2]);
  and a13(w1[3], sel, i0[3]);
  and a14(w1[4], sel, i0[4]);
  and a15(w1[5], sel, i0[5]);
  and a16(w1[6], sel, i0[6]);
  and a17(w1[7], sel, i0[7]);
  
  and a20(w2[0], ~sel, i1[0]);
  and a21(w2[1], ~sel, i1[1]);
  and a22(w2[2], ~sel, i1[2]);
  and a23(w2[3], ~sel, i1[3]);
  and a24(w2[4], ~sel, i1[4]);
  and a25(w2[5], ~sel, i1[5]);
  and a26(w2[6], ~sel, i1[6]);
  and a27(w2[7], ~sel, i1[7]);
  
  or o7(out[7], w1[7], w2[7]);
  or o6(out[6], w1[6], w2[6]);
  or o5(out[5], w1[5], w2[5]);
  or o4(out[4], w1[4], w2[4]);
  or o3(out[3], w1[3], w2[3]);
  or o2(out[2], w1[2], w2[2]);
  or o1(out[1], w1[1], w2[1]);
  or o0(out[0], w1[0], w2[0]);
  
endmodule

module Mux_4x1(i0, i1, i2, i3, sel, out);
  input i0, i1, i2, i3;
  input [1:0] sel;
  output out;
  wire w0, w1, w2, w3;
  
  and a0(w0, ~sel[1], ~sel[0], i0);
  and a1(w1, ~sel[1], sel[0], i1);
  and a2(w2, sel[1], ~sel[0], i2);
  and a3(w3, sel[1], sel[0], i3);
  or o1(out, w0, w1, w2, w3);
  
endmodule

module Link(i0, i1, out);
  
  input [7:0] i0, i1;
  output [15:0] out;
  
  assign out[15:8] = i0[7:0];
  assign out[7:0] = i1[7:0];


endmodule

module Shifter(i, out);
  
  input [15:0] i;
  output [15:0] out;
  
  assign out[14:0] = i[15:1];
  assign out[15] = 0;
  
endmodule

